import { FC, useState, MouseEvent, useEffect } from 'react';
import classnames from 'classnames';
import styles from './Editor.module.less';
import { alignConfig } from './config';
import { getBlockMatch, getMatchKeyOfObject } from '@/core/utils/get';
import { useSlate } from 'slate-react';
import { setBlockNode } from '@/core/utils/set';
import { PLUGINS_KEYS } from '@/plugins/types';
import { Editor, Element } from 'slate';
import { DEFAULT_ALIGN } from '@/plugins/config';

interface IProps {
  toobarDom: HTMLDivElement | null;
}

const Align: FC<IProps> = ({ toobarDom }) => {
  const editor = useSlate();
  const [selectAlign, setSelectAlign] = useState({
    show: false,
    align: alignConfig[0].value,
  });

  useEffect(() => {
    function documentClick() {
      setSelectAlign((origin) => ({
        ...origin,
        show: false,
      }));
    }
    document.addEventListener('click', documentClick);
    return () => {
      document.removeEventListener('click', documentClick);
    };
  }, []);

  const setBlockAlign = (event: MouseEvent<HTMLSpanElement>, align?: string) => {
    event.stopPropagation();
    const nodes = Editor.nodes(editor);
    let value = align || DEFAULT_ALIGN;
    try {
      const { block } = getBlockMatch(editor);
      const type = getMatchKeyOfObject(block.align || {}) || '';

      value = align || type || DEFAULT_ALIGN;

      setBlockNode(editor, {
        [PLUGINS_KEYS.ALIGN]: {
          [value]: true,
        },
      });
    } catch (error) {
      for (const match of nodes) {
        const [block, path] = match;
        if (Element.isElement(block) && Editor.isBlock(editor, block) && !Editor.isEditor(block)) {
          const type = getMatchKeyOfObject(block.align || {}) || '';
          value = align || type || DEFAULT_ALIGN;
          setBlockNode(
            editor,
            {
              [PLUGINS_KEYS.ALIGN]: {
                [value]: true,
              },
            },
            {
              at: path,
            }
          );
        }
      }
    } finally {
      setSelectAlign((origin) => ({
        ...origin,
        show: !align,
        align: value || origin.align,
      }));
    }
  };

  return (
    <li className={classnames(styles['toobar-item'])}>
      <span onClick={(event) => setBlockAlign(event)} className={`${styles['align-apply']} ${styles['toobar-item-hover-span']}`}>
        <svg id="3495779.2999999523-27142905780" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 54" width="30">
          <g id="3495779.2999999523-6151213783">
            <g id="3495779.2999999523-77298159111">
              <path
                id="3495779.2999999523-65425281837"
                d="M18 18h24v2H18v-2zm0 8h24v2H18v-2zm0 8h24v2H18v-2zm0-12h16v2H18v-2zm0 8h16v2H18v-2z"
              ></path>
            </g>
          </g>
        </svg>
        <span className={`${styles['arrow-icon']} ${styles['align-icon']}`}></span>
      </span>
      {selectAlign.show && (
        <div
          className={styles['select-dropdown']}
          style={{
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            // @ts-ignore
            '--top': toobarDom?.clientHeight + 'px',
          }}
        >
          <div className={styles['list-holder']}>
            {alignConfig.map((item) => {
              return (
                <div key={item.value} onClick={(event) => setBlockAlign(event, item.value)} className={styles['list-item']} title={item.label}>
                  <div className={styles['list-item-content']} dangerouslySetInnerHTML={{ __html: item.html }}></div>
                  {selectAlign.align === item.value && (
                    <div className={styles['list-item-active']}>
                      <svg id="4261481.399999976-198592047" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="10">
                        <g id="4261481.399999976-32361485383">
                          <g id="4261481.399999976-47527160306">
                            <path
                              id="4261481.399999976-6819894631"
                              fill="none"
                              stroke="#999"
                              strokeWidth="3.6"
                              d="M20.5 6.4L9.2 17.7l-5.7-5.6"
                            ></path>
                          </g>
                        </g>
                      </svg>
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      )}
    </li>
  );
};

export default Align;
